package com.baidu.che.codriversdk;

import android.app.Notification;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import com.baidu.che.codriver.ICoDriverListener;
import com.baidu.che.codriver.ICoDriverService;
import com.baidu.che.codriversdk.handler.MusicCommandHandler;
import com.baidu.che.codriversdk.handler.b;
import com.baidu.che.codriversdk.handler.c;
import com.baidu.che.codriversdk.handler.d;
import com.baidu.che.codriversdk.handler.e;
import com.baidu.che.codriversdk.handler.f;
import com.baidu.che.codriversdk.handler.g;
import com.baidu.che.codriversdk.handler.h;
import com.baidu.che.codriversdk.handler.i;
import com.baidu.che.codriversdk.handler.j;
import com.baidu.che.codriversdk.handler.k;
import com.baidu.che.codriversdk.handler.l;
import com.baidu.che.codriversdk.handler.m;
import com.baidu.che.codriversdk.handler.n;
import com.baidu.che.codriversdk.handler.o;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class PlatformService extends Service implements INoProguard {
    public static final String TAG = "PlatformService";
    public static final int CONNECT = 101;
    private static final String CO_DRIVER = "com.baidu.che.codriver"; //DuerOS
    private static final String CO_DRIVER_SERVICE = "com.baidu.che.codriver.sdk.CoDriverService";
    private static final String INIT_SUCCESS = "init.success";

    // 创建Binder对象实例,Binder用于进程间通信
    // Binder用于解包Parcel对象(Proxy和Server传给Binder Driver的Parcel对象)
    private PlatformService.a mBinder = new PlatformService.a();

    /*
    * HandlerThread本质上是一个线程类,它继承了Thread
    * HandlerThread有自己的内部Looper对象,可以进行looper循环
    * 通过获取HandlerThread的looper对象传递给Handler对象,可以在handleMessage方法中执行异步任务
    * 创建HandlerThread后必须先调用HandlerThread.start()方法,Thread会先调用run方法，创建Looper对象
    * 循环器Looper是消息队列与Handler的通信媒介
    */

    // 创建HandlerThread对象,传入参数的作用主要是标记当前线程的名字
    private HandlerThread mRequestThread = new HandlerThread("RequestThread");

    // Handler:主线程与子线程的通信媒介，用于处理线程的消息(Message)
    // 使用Handler的原因：将工作线程需操作UI的消息传递到主线程,使得主线程可根据工作线程的需求更新UI,从而避免线程操作不安全的问题.

    // 工作Handler
    private Handler mWorkHandler;
    // 主Handler
    private Handler mMainHandler;

    // ICoDriverService继承IInterface,IInterface是Binder的基类
    // IInterface代表的就是服务端进程具备什么样的功能
    // ICoDriverService继承IInterface表明该类具备服务端的Service功能
    private ICoDriverService mCoDriverService;

    private boolean mIsInitSuccess = false;
    private boolean mIsSystemSleep = false;

    // 命令HandlerMap
    private Map<String, com.baidu.che.codriversdk.RequestManager.a> mCmdHandlerMap;

    // 用于监听Service状态的接口
    // 当进行bindService调用的时候，需要传递一个ServiceConnection
    // 当service创建完毕之后，会回调ServiceConnection的方法来通知调用方，即bindService是异步的
    // 根本原因在于service的onCreate/onStartCommand生命周期相关的方法总是在主线程上执行的
    // 如果bindService在主线程上阻塞的话,service就无法执行上述生命周期相关的方法，完成初始化工作
    // 既然不能阻塞，只好通过ServiceConnection来回调通知了
    // 客户端可以调用bindService()绑定到一个service,之后系统调用service的onBind()方法返回一个用来与service交互的IBinder
    private ServiceConnection mServiceConnection = new ServiceConnection() {

        // 系统调用这个方法来传递在service的onBind()中返回的IBinder
        public void onServiceConnected(ComponentName name, IBinder service) {
            LogUtil.d("PlatformService", "onServiceConnected ComponentName=" + name.getPackageName());

            // 初始化服务端的mCoDriverService
            // a是ICoDriverService的抽象静态内部类继承Binder用于进程间通信
            PlatformService.this.mCoDriverService = com.baidu.che.codriver.ICoDriverService.a.a(service);

            try {
                // 通过Binder驱动向ServiceManager中注册PlatformService服务
                PlatformService.this.mCoDriverService.registerListener(PlatformService.this.getPackageName(), PlatformService.this.mListener);
            } catch (RemoteException var4) {
                var4.printStackTrace();
            }
        }

        // 当客户端解除绑定时,这个方法不会被调用,Service崩溃或被强制停止时调用此方法
        public void onServiceDisconnected(ComponentName name) {
            LogUtil.d("PlatformService", "onServiceDisconnected ComponentName=" + name.getPackageName());

            PlatformService.this.mCoDriverService = null;
            PlatformService.this.mIsInitSuccess = false;

            //断开连接后的相关操作
            RequestManager.getInstance().doAfterRemoteDisconnected();
            //断线重连
            PlatformService.this.reConnect();
        }
    };


    // ICoDriverListener继承IInterface
    // a是ICoDriverListener的抽象静态内部类继承Binder用于进程间通信
    private ICoDriverListener mListener = new com.baidu.che.codriver.ICoDriverListener.a() {

        public String onCommand(String pkg, final String cmd, final String param, final String data) throws RemoteException {

            // 主Handler调用post方法将消息发送到消息队列中
            PlatformService.this.mMainHandler.post(new Runnable() {
                public void run() {
                    LogUtil.d("PlatformService", "onCommand cmd=" + cmd + " param=" + param);

                    // 从命令HandlerMap中取出当前cmd并初始化RequestManager中的接口a
                    PlatformService.this.dispatch(cmd, param, data);
                }
            });
            return null;
        }
    };

    public PlatformService() {
    }

    public IBinder onBind(Intent intent) {
        LogUtil.d("PlatformService", "onBind");

        // 返回PlatformService中的Binder对象实例
        return this.mBinder;
    }

    public void onCreate() {
        super.onCreate();
        LogUtil.d("PlatformService", "onCreate");

        //使此服务在前台运行,提供正在进行的服务在此状态下向用户显示的通知.
        this.startForeground(8888, new Notification());

        this.init();

        this.reConnect();
    }

    private void init() {
        // 实例化主Handler
        // Looper.getMainLooper()：返回应用程序的主循环器,存在于主线程中

        this.mMainHandler = new Handler(Looper.getMainLooper()) {
            // 重写Handler的handlerMessage方法,参数就是从其他线程传递过来的消息
            // mMainHandler所在的线程通过handlerMessage方法就能收到具体的信息了
            public void handleMessage(Message msg) {
                super.handleMessage(msg);

                //通过what值判断消息的来源
                switch(msg.what) {
                    case 101:
                        //如果消息来源是101(服务端传过来的消息),PlatformService重新连接
                        PlatformService.this.reConnect();
                    default:
                }
            }
        };

        //请求线程开始执行
        this.mRequestThread.start();

        //实例化工作Handler参数为Looper对象, getLooper()返回与HandlerThread相关联的looper
        //线程开启后getLooper()会一直等待知道looper被创建
        this.mWorkHandler = new Handler(this.mRequestThread.getLooper());

        this.mCmdHandlerMap = new ConcurrentHashMap();

        //添加所有的命令Handler
        this.addAllCommandHandler();
    }

    private void addAllCommandHandler() {

        //将相关命令和Handler添加到cmdHandlerMap中
        this.addCommandHandler("init.success", new com.baidu.che.codriversdk.RequestManager.a() {
            public String a(String cmd, String param, String data) {
                PlatformService.this.mIsInitSuccess = true;
                RequestManager.getInstance().doAfterConnectedToRemote();
                return null;
            }
        });

        this.addCommandHandler("asr.tool", new com.baidu.che.codriversdk.handler.a());
        this.addCommandHandler("bt.tool", new b());
        this.addCommandHandler("config.tool", new e());
        this.addCommandHandler("hardkey.tool", new f());
        this.addCommandHandler("media.tool", new g());
        this.addCommandHandler("music.tool", new MusicCommandHandler());
        this.addCommandHandler("map.tool", new h());
        this.addCommandHandler("phone.tool", new i());
        this.addCommandHandler("player.tool", new j());
        this.addCommandHandler("private_radio.tool", new k());
        this.addCommandHandler("record.tool", new l());
        this.addCommandHandler("system.tool", new m());
        this.addCommandHandler("camera.tool", new c());
        this.addCommandHandler("tts.tool", new n());
        this.addCommandHandler("wechat.tool", new o());
        this.addCommandHandler("carInfo.tool", new d());
    }

    //开启服务端Service连接至Server
    private void connect() {
        LogUtil.d("PlatformService", "connect to codriver");

        Intent startIntent = new Intent("com.baidu.che.codriver.StartService");
        ComponentName componentName = new ComponentName("com.baidu.che.codriver", "com.baidu.che.codriver.sdk.CoDriverService"); // 包名 类名
        //设置组件以处理Intent
        startIntent.setComponent(componentName);
        //启动服务端Service
        this.startService(startIntent);

        //当前PlatformService与远端Service绑定
        //客户端调用bindService()绑定到一个service,之后系统调用service的onBind()方法返回一个用来与service交互的IBinder
        //mServiceConnection中进行了远端Service的初始化操作
        this.bindService(startIntent, this.mServiceConnection, 1);
    }

    private void reConnect() {
        if (this.mCoDriverService == null) {
            if (!this.mIsSystemSleep) {
                LogUtil.d("PlatformService", "reConnect");

                //开启服务端Service连接至Server
                this.connect();
            }

            //主Handler发送仅包含在指定的时间过后传递的值的消息
            this.mMainHandler.sendEmptyMessageDelayed(101, 5000L);
        }
    }

    public void onDestroy() {
        super.onDestroy();
        LogUtil.d("PlatformService", "onDestroy");

        //主Handler移除服务端进程消息
        this.mMainHandler.removeMessages(101);
    }

    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    boolean isConnectedToRemote() {
        return this.mIsInitSuccess;
    }

    boolean isSystemSleep() {
        return this.mIsSystemSleep;
    }

    void setIsSystemSleep(boolean isSystemSleep) {
        this.mIsSystemSleep = isSystemSleep;
    }

    void sendRequest(final String cmd, final String param, final String data) {
        LogUtil.d("PlatformService", "sendRequest " + cmd + " " + param);
        if (this.mCoDriverService != null) {
            this.mWorkHandler.post(new Runnable() {
                public void run() {
                    if (PlatformService.this.mCoDriverService != null) {
                        try {
                            PlatformService.this.mCoDriverService.sendCommand(PlatformService.this.getPackageName(), cmd, param, data);
                        } catch (RemoteException var2) {
                            var2.printStackTrace();
                        }
                    }

                }
            });
        } else {
            this.reConnect();
        }
    }

    void addCommandHandler(String cmd, com.baidu.che.codriversdk.RequestManager.a commandHandler) {
        this.mCmdHandlerMap.put(cmd, commandHandler);
    }

    public com.baidu.che.codriversdk.RequestManager.a getHandler(String cmd) {
        return (com.baidu.che.codriversdk.RequestManager.a)this.mCmdHandlerMap.get(cmd);
    }

    private void dispatch(String cmd, String param, String data) {
        com.baidu.che.codriversdk.RequestManager.a commandHandler = (com.baidu.che.codriversdk.RequestManager.a)this.mCmdHandlerMap.get(cmd);
        if (commandHandler != null) {
            commandHandler.a(cmd, param, data);
        }
    }

    public int feedAudioBuffer(byte[] micData, byte[] spkData) {
        if (this.mCoDriverService != null) {
            try {
                this.mCoDriverService.feedAudioBuffer(micData, spkData);
            } catch (Exception var4) {
                var4.printStackTrace();
                return -1;
            }

            return micData.length;
        } else {
            return -1;
        }
    }

    public int feedRawAudioBuffer(byte[] rawData) {
        if (this.mCoDriverService != null) {
            try {
                this.mCoDriverService.feedRawAudioBuffer(rawData);
            } catch (Exception var3) {
                var3.printStackTrace();
                return -1;
            }

            return rawData.length;
        } else {
            return -1;
        }
    }

    /* a是PlatformService的内部类继承Binder
     * Binder用于IPC,基于Client-Server通信模式
     * a中有方法a()返回当前PlatformService的对象
     */
    class a extends Binder {
        a() {
        }

        PlatformService a() {
            return PlatformService.this;
        }
    }
}
